											library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity controller is

port(
	clock: in std_logic; 

	--what the formula gave back after the last assignment
	result: in std_logic;		   
	
	--no more assignments left so stop going
	none: in std_logic;
	
	g_reset: in std_logic;
	enable: in std_logic;
	
	f_enable: out std_logic;
	o_enable: out std_logic;
	a_enable: out std_logic
);
end entity controller;

architecture controller_behavior of controller is
--define enumerated states
type State is(Reset, Formula, Assignment, Output);

--declare state signals
signal next_state: State := Reset;
signal current_state: State := Reset;

--internal signals, used to represent output signals (can't change output signals directly)
signal f_temp: std_logic := '0';
signal o_temp: std_logic := '0';
signal a_temp: std_logic := '0';

begin

--state switching process
process(g_reset, clock)

begin		
	--asynchronous reset
	if g_reset = '1' then
		current_state <= Reset;
		
	elsif rising_edge(clock) then
		current_state <= next_state;
		
	end if;
end process;

process(result, enable, current_state)

begin

case current_state is
	
	when Reset =>
		a_temp <= '0';
		o_temp <= '0';
		f_temp <= '0';
	
		if enable = '1' then
			next_state <= Formula;

		else
			next_state <= Reset;
			
		end if;
	
	when Formula =>
	
		a_temp <= '0';
		o_temp <= '0';
		f_temp <= '1';
		
		if none = '1' or result = '1' then

			
			next_state <= Output;
			
		else

			
			next_state <= Assignment;
			
		end if;	
		
	when Assignment =>	 
	
		a_temp <= '1';
		o_temp <= '0';
		f_temp <= '0';

		next_state <= Formula;
		
	when Output =>

		a_temp <= '0';
		o_temp <= '1';
		f_temp <= '0';
		
		next_state <= Reset;
		
end case;		

end process;

f_enable <= f_temp;
o_enable <= o_temp; 
a_enable <= a_temp; 
		
end architecture controller_behavior;			